package com.example.joke.proxy

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.joke.R
import com.example.joke.proxy.star.BigStar
import com.example.joke.proxy.star.IStar
import com.example.joke.proxy.star.ProxyUtil
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

class ProxyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_proxy)
        // 静态代理示例
        val custom = Custom()
        val employee = BankEmployee(custom)
        employee.makeCard()
        employee.changePwd()

        // 动态代理示例、
        // 获取了代理，代理了所有的方法，而且都会走InvocationHandler里面的invoke方法
        // 动态代理源码解析：解析interface所有方法，新建一个class，class的名字是：包名+$Proxy
        // 实例化了proxy对象，proxy的里面包含InvocationHandler
        // 每次调方法其实执行的是InvocationHandler里面的invoke方法
        val proxy: IOperate = Proxy.newProxyInstance(
            custom.javaClass.classLoader,
            custom.javaClass.interfaces,
            BankInvocationHandler(custom)
        ) as IOperate

        proxy.makeCard()
        proxy.changePwd()

        val proxy1: IOperate = Proxy.newProxyInstance(
            custom.javaClass.classLoader,
            custom.javaClass.interfaces
        ) { _, method, args ->
            Log.d("bank-dynamic---Employee：", "办理业务前的准备工作")
            val obj: Any? = method?.invoke(custom, *args.orEmpty())
            Log.d("bank-dynamic---Employee：", "业务办理完毕")
            obj
        } as IOperate
        proxy1.makeCard()

        dynamicProxy()
    }

    private fun dynamicProxy() {
        val bigStar = BigStar("张韶涵")
        val startProxy: IStar = ProxyUtil.createProxy(bigStar)
        startProxy.sing("淋雨一直走")
        startProxy.dance()
    }

    class BankInvocationHandler(private val custom: IOperate) : InvocationHandler {

        @Throws(Throwable::class)
        override fun invoke(p0: Any?, method: Method, objects: Array<out Any>?): Any? {
            Log.d("bank---Employee：", "办理业务前的准备工作")
            val obj: Any? = method.invoke(custom, *objects.orEmpty())
            Log.d("bank---Employee：", "业务办理完毕")
            return obj
        }

    }
}